package com.shawn.spring.boot.flowable.service.impl;

import com.shawn.spring.boot.flowable.bo.ProcessDefinitionBO;
import com.shawn.spring.boot.flowable.service.FlowableService;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.Task;
import org.flowable.engine.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
public class FlowableServiceImpl implements FlowableService {

  @Autowired private RuntimeService runtimeService;

  @Autowired private TaskService taskService;

  @Autowired private RepositoryService repositoryService;

  @Autowired private HistoryService historyService;

  @Override
  @Transactional
  public void startProcessInstance() {
    runtimeService.startProcessInstanceByKey("oneTaskProcess");
  }

  @Transactional
  public List<Task> getTasks(String assignee) {
    return taskService.createTaskQuery().taskAssignee(assignee).list();
  }

  @Override
  public void checkProcessHistory(String processId) {
    List<HistoricActivityInstance> activities =
        historyService
            .createHistoricActivityInstanceQuery()
            .processInstanceId(processId)
            .finished()
            .orderByHistoricActivityInstanceEndTime()
            .asc()
            .list();

    for (HistoricActivityInstance activity : activities) {
      log.info("{} took {} ms", activity.getActivityId(), activity.getDurationInMillis());
    }
  }

  @Override
  public List<Task> getTasksByGroup(String group) {
    List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(group).list();
    return tasks;
  }

  @Override
  public ProcessDefinitionBO getProcessDefinition(String deploymentId) {
    ProcessDefinition processDefinition =
        repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();

    return ProcessDefinitionBO.builder()
        .id(processDefinition.getId())
        .key(processDefinition.getKey())
        .build();
  }

  @Override
  public List<Task> getTasksByGroupOrAssign(String assign) {
    List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(assign).list();
    return tasks;
  }
}
